package com.mycompany.services.initializer;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.mycompany.optimizaproject.CategoriaUsuario;
import com.mycompany.optimizaproject.ClasificacionIncidente;
import com.mycompany.optimizaproject.Cliente;
import com.mycompany.optimizaproject.Estado;
import com.mycompany.optimizaproject.Incidente;
import com.mycompany.optimizaproject.MotivoRechazo;
import com.mycompany.optimizaproject.Prioridad;
import com.mycompany.optimizaproject.Solucion;
import com.mycompany.optimizaproject.TipoIncidente;
import com.mycompany.optimizaproject.TipoIncidenteExtra;
import com.mycompany.optimizaproject.Usuario;
import com.mycompany.services.dao.CategoriaUsuarioDAO;
import com.mycompany.services.dao.ClasificacionIncidenteDAO;
import com.mycompany.services.dao.ClasificacionIncidenteXUsuarioDAO;
import com.mycompany.services.dao.ClienteDAO;
import com.mycompany.services.dao.EstadoDAO;
import com.mycompany.services.dao.IncidenteDAO;
import com.mycompany.services.dao.MotivoRechazoDAO;
import com.mycompany.services.dao.PrioridadDAO;
import com.mycompany.services.dao.SolucionDAO;
import com.mycompany.services.dao.TipoIncidenteDAO;
import com.mycompany.services.dao.TipoIncidenteExtraDAO;
import com.mycompany.services.dao.UsuarioDAO;

public class OptimizaEntityInitializer {
	@Autowired
	protected PlatformTransactionManager transactionManager;

	protected TransactionTemplate transactionTemplate;

	@Autowired
	protected CategoriaUsuarioDAO categoriaUsuarioDAO;

	@Autowired
	protected ClasificacionIncidenteDAO clasificacionIncidenteDAO;

	@Autowired
	protected ClasificacionIncidenteXUsuarioDAO clasificacionIncidenteXUsuarioDAO;

	@Autowired
	protected ClienteDAO clienteDAO;

	@Autowired
	protected EstadoDAO estadoDAO;

	@Autowired
	protected IncidenteDAO incidenteDAO;

	@Autowired
	protected MotivoRechazoDAO motivoRechazoDAO;

	@Autowired
	protected PrioridadDAO prioridadDAO;

	@Autowired
	protected SolucionDAO solucionDAO;

	@Autowired
	protected TipoIncidenteDAO tipoIncidenteDAO;

	@Autowired
	protected TipoIncidenteExtraDAO tipoIncidenteExtraDAO;

	@Autowired
	protected UsuarioDAO usuarioDAO;

	public void init() {
		transactionTemplate = new TransactionTemplate(transactionManager);
		transactionTemplate.execute(new TransactionCallback() {

			@Override
			public Object doInTransaction(TransactionStatus status) {
				if (usuarioDAO.getList().size() == 0) {// Si la DB esta vacia
					CategoriaUsuario catCliente = createCatUser("cliente", "Cliente");
					categoriaUsuarioDAO.save(catCliente);
					CategoriaUsuario catTecnico = createCatUser("tecnico", "Tecnico");
					categoriaUsuarioDAO.save(catTecnico);
					CategoriaUsuario catAdmin = createCatUser("sys_admin", "SYS-ADMIN");
					categoriaUsuarioDAO.save(catAdmin);
					
					usuarioDAO.save(createUser("jolivera", "1234", "Olivera", "Juan", "jolivera@gio.com", "jolivera2@gio.com", false, null, "59832", catCliente.getId()));
				
					ClasificacionIncidente claIncHWSW = createClaIncidente("Hardware/Software", false);
					clasificacionIncidenteDAO.save(claIncHWSW);
					ClasificacionIncidente claIncDB = createClaIncidente("Database", false);
					clasificacionIncidenteDAO.save(claIncDB);
					ClasificacionIncidente claIncInfra = createClaIncidente("Infraestructure", false);
					clasificacionIncidenteDAO.save(claIncInfra);
					ClasificacionIncidente claIncTel = createClaIncidente("Telecommunication", false);
					clasificacionIncidenteDAO.save(claIncTel);
					ClasificacionIncidente claIncSec = createClaIncidente("Security", false);
					clasificacionIncidenteDAO.save(claIncSec);
					ClasificacionIncidente claIncOfi = createClaIncidente("Ofimatica", false);
					clasificacionIncidenteDAO.save(claIncOfi);
					
					clienteDAO.save(createCliente("IBM", "IBM S.A.", "0685498", "08001111", "Colonia", "1171", "ibm@ibm.com", "ibm@ibm.com", "-54.5548,35.546", null, false));
					clienteDAO.save(createCliente("Sony", "Sony S.A.", "0655478", "08002222", "Soriano", "1271", "sony@facebook.com", "sony@facebook.com", "-54.5548,35.546", null, false));
					
					estadoDAO.save(createEstado("Solicitado"));
					Estado estadoRechazo = createEstado("Rechazado");
					estadoDAO.save(estadoRechazo);
					estadoDAO.save(createEstado("Stand By"));
					estadoDAO.save(createEstado("Asignado"));
					estadoDAO.save(createEstado("Cerrado"));
					
					motivoRechazoDAO.save(createMotivoRechazo("No Rechazado", estadoRechazo.getId()));
					motivoRechazoDAO.save(createMotivoRechazo("Tercero", estadoRechazo.getId()));
					motivoRechazoDAO.save(createMotivoRechazo("Usuario", estadoRechazo.getId()));
					motivoRechazoDAO.save(createMotivoRechazo("Esperando Autorizacion", estadoRechazo.getId()));
					
					prioridadDAO.save(createPrioridad("Baja"));
					prioridadDAO.save(createPrioridad("Media"));
					prioridadDAO.save(createPrioridad("Critica"));
					
					TipoIncidente tipoIncPC = createTipoIncidente("PC", claIncHWSW.getId(), false);
					tipoIncidenteDAO.save(tipoIncPC);
					
					tipoIncidenteDAO.save(createTipoIncidente("Notebook", claIncHWSW.getId(), false));
					tipoIncidenteDAO.save(createTipoIncidente("Impresora", claIncHWSW.getId(), false));
					tipoIncidenteDAO.save(createTipoIncidente("MSSQL", claIncDB.getId(), false));
					TipoIncidente tipoIncOracle = createTipoIncidente("Oracle", claIncDB.getId(), false);
					tipoIncidenteDAO.save(tipoIncOracle);
					tipoIncidenteDAO.save(createTipoIncidente("Tipo infra", claIncInfra.getId(), false));
					tipoIncidenteDAO.save(createTipoIncidente("Tipo Sec", claIncSec.getId(), false));
					tipoIncidenteDAO.save(createTipoIncidente("Tipo Ofi", claIncOfi.getId(), false));
					tipoIncidenteDAO.save(createTipoIncidente("Tipo Tel", claIncTel.getId(), false));
					
					
					tipoIncidenteExtraDAO.save(createTipoIncidenteExtra("IBM", tipoIncPC.getId(), false));
					tipoIncidenteExtraDAO.save(createTipoIncidenteExtra("Clone", tipoIncPC.getId(), false));
					tipoIncidenteExtraDAO.save(createTipoIncidenteExtra("Version 9", tipoIncOracle.getId(), false));
					tipoIncidenteExtraDAO.save(createTipoIncidenteExtra("Version 8", tipoIncOracle.getId(), false));
					
					incidenteDAO.save(createIncidente("Nuevo Incidente", new Date(), 1, "Detalle del nuevo incidente", 2, 1, 2, 95, 2, new Date(), 1, null, false));
					incidenteDAO.save(createIncidente("Nuevo Incidente2", new Date(), 1, "Detalle del nuevo incidente2", 2, 1, 2, 92, 2, new Date(), 2, null, false));
					incidenteDAO.save(createIncidente("Nuevo Incidente3", new Date(), 2, "Detalle del nuevo incidente3", 2, 1, 2, 94, 2, new Date(), 1, null, false));
					incidenteDAO.save(createIncidente("Nuevo Incidente4", new Date(), 2, "Detalle del nuevo incidente4", 2, 1, 2, 96, 2, new Date(), 2, null, false));
					
				}
				return null;
			}
		});
	}

	private Usuario createUser(final String username, final String password,
			final String apellido, final String nombre, final String email,
			final String email2, final boolean baja, final Date fechaBaja,
			final String telefono, final int idCategoriaUsuario) {
		return (Usuario) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public Usuario doInTransaction(TransactionStatus status) {
				Usuario user = new Usuario();
				user.setUsuario(username);
				user.setPassword(password);
				user.setNombre(nombre);
				user.setApellido(apellido);
				user.setEmail(email);
				user.setEmail2(email2);
				user.setBaja(baja);
				user.setFechaBaja(fechaBaja);
				user.setTelefono(telefono);
				user.setIdCategoriaUsuario(idCategoriaUsuario);
				return user;
			}
		});
	}

	private CategoriaUsuario createCatUser(final String nombre, final String descripcion) {
		return (CategoriaUsuario) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public CategoriaUsuario doInTransaction(TransactionStatus status) {
				CategoriaUsuario cat = new CategoriaUsuario();
				cat.setNombreCategoria(nombre);
				cat.setDescrCategoria(descripcion);
				return cat;
			}
		});
	}
	
	private ClasificacionIncidente createClaIncidente(final String descripcion, final boolean baja) {
		return (ClasificacionIncidente) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public ClasificacionIncidente doInTransaction(TransactionStatus status) {
				ClasificacionIncidente cla = new ClasificacionIncidente();
				cla.setDescClasificacionIncidente(descripcion);
				cla.setBaja(baja);
				return cla;
			}
		});
	}
	private Cliente createCliente(final String nombreFantasia,
								  final String razonSocial,
								  final String rut,
								  final String telefono,
								  final String calle,
								  final String numero,
								  final String email,
								  final String email2,
								  final String googleaxis,
								  final Date fecBaja,
								  final boolean baja) {
		return (Cliente) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public Cliente doInTransaction(TransactionStatus status) {
				Cliente c = new Cliente();
				c.setNombreFantasia(nombreFantasia);
				c.setRazonSocial(razonSocial);
				c.setRut(rut);
				c.setTelefono(telefono);
				c.setCalle(calle);
				c.setNumero(numero);
				c.setEmail(email);
				c.setEmail2(email2);
				c.setGoogleaxis(googleaxis);
				c.setBaja(baja);
				c.setFecBaja(fecBaja);
				return c;
			}
		});
	}
	private Estado createEstado(final String descripcion) {
		return (Estado) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public Estado doInTransaction(TransactionStatus status) {
				Estado estado = new Estado();
				estado.setDescrEstado(descripcion);
				return estado;
			}
		});
	}
	private MotivoRechazo createMotivoRechazo(final String descripcion, final int idEstado) {
		return (MotivoRechazo) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public MotivoRechazo doInTransaction(TransactionStatus status) {
				MotivoRechazo motivo = new MotivoRechazo();
				motivo.setDescMotivo(descripcion);
				motivo.setIdEstado(idEstado);
				return motivo;
			}
		});
	}

	private Prioridad createPrioridad(final String descripcion) {
		return (Prioridad) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public Prioridad doInTransaction(TransactionStatus status) {
				Prioridad p = new Prioridad();
				p.setDescrPrioridad(descripcion);
				return p;
			}
		});
	}
	private TipoIncidente createTipoIncidente(final String descripcion,
											  final int idClasificacionIncidente,
											  final boolean baja) {
		return (TipoIncidente) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public TipoIncidente doInTransaction(TransactionStatus status) {
				TipoIncidente t = new TipoIncidente();
				t.setDescrTipoIncidente(descripcion);
				t.setIdClasificacionIncidente(idClasificacionIncidente);
				t.setBaja(baja);
				return t;
			}
		});
	}
	private TipoIncidenteExtra createTipoIncidenteExtra(final String descripcion,
													    final int idTipoIncidente,
													    final boolean baja) {
		return (TipoIncidenteExtra) transactionTemplate.execute(new TransactionCallback() {

			@Override
			public TipoIncidenteExtra doInTransaction(TransactionStatus status) {
				TipoIncidenteExtra t = new TipoIncidenteExtra();
				t.setDescrTipoIncidenteExtra(descripcion);
				t.setIdTipoIncidente(idTipoIncidente);
				t.setBaja(baja);
				return t;
			}
		});
	}

	private Incidente createIncidente(final String titulo,
									  final Date fechaInicio,
									  final int idCliente,
									  final String detalle,
									  final int idPrioridad,
									  final int idClasificacionIncidente,
									  final int idTipoIncidente,
									  final int idTipoIncidenteExtra,
									  final int idEstado,
									  final Date fechaAsignado, 
									  final int idUsuarioSol,
									  final Date fechaFin,
									  final boolean baja) {	
		return (Incidente) transactionTemplate
				.execute(new TransactionCallback() {

					@Override
					public Incidente doInTransaction(TransactionStatus status) {
						Incidente i = new Incidente();
						i.setTitulo(titulo);
						i.setFechaInicio(fechaInicio);
						i.setIdCliente(idCliente);
						i.setDetalle(detalle);
						i.setIdPrioridad(idPrioridad);
						i.setIdClasificacionIncidente(idClasificacionIncidente);
						i.setIdTipoIncidente(idTipoIncidente);
						i.setIdTipoIncidenteExtra(idTipoIncidenteExtra);
						i.setIdEstado(idEstado);
						i.setFechaAsignado(fechaAsignado);
						i.setIdUsuarioSol(idUsuarioSol);
						i.setFechaFin(fechaFin);
						
						return i;
					}
				});
	}
}
